// 1.什么是jwt？
// JSON Web Token（JWT）是目前最流行的跨域身份验证解决方案
// 解决问题：session不支持分布式架构，无法支持横向扩展，只能通过数据库来保存会话数据实现共享。如果持久层失败会出现认证失败。
// 优点：服务器不保存任何会话数据，即服务器变为无状态，使其更容易扩展。

// 2. JWT包含了使用.分隔的三部分
// Header头部，例如{ "alg": "HS256", "typ": "JWT"}   
// Payload负载载荷
//     JWT 规定了7个官方字段:
//     iss (issuer)：签发人
//     exp (expiration time)：过期时间
//     sub (subject)：主题
//     aud (audience)：受众
//     nbf (Not Before)：生效时间
//     iat (Issued At)：签发时间
//     jti (JWT ID)：编号
// Signature签名,对前两部分的签名，防止数据篡改,手段就是加密+加盐


// JWT 作为一个令牌（token），有些场合可能会放到 URL（比如 api.example.com/?token=xxx）。
// Base64 有三个字符+、/和=，在 URL 里面有特殊含义，所以要被替换掉：=被省略、+替换成-，/替换成_ 。这就是 Base64URL 算法。

// 使用方式
// HTTP 请求的头信息Authorization字段里面
// Authorization: Bearer <token>

// 通过url传输
// http://www.xxx.com/pwa?token=xxxxx
// 如果是post请求也可以放在请求体中


const http = require('http');
const crpto = require('crypto');
// const jwt = require('jwt-simple'); //  jsonwebtoken
// jwt 的核心就是生成令牌，验证令牌
let secret = 'ikki'


const jwt = {
    base64urlEscape(str){ //这几个字符在url中有特殊含义,因此需要转化
        return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '')
    },
    sign(content, secret) { //加密
        return  this.base64urlEscape(crpto.createHmac('sha256',secret).update(content).digest('base64'))
    },
    toBase64(content){
        if (typeof content == 'object') {
            content = JSON.stringify(content)
        }
        return this.base64urlEscape(Buffer.from(content).toString('base64'));
    },
    encode(payload,secret){
        const part1 = this.toBase64({ "typ": "JWT", "alg": "HS256" })
        const part2 = this.toBase64(payload)
        const part3 = this.sign([part1, part2].join('.'), secret);
        return part1 + '.' + part2 + '.' + part3
    },
    base64urlUnescape(str) {
        str += new Array(5 - str.length % 4).join('=');
        return str.replace(/\-/g, '+').replace(/_/g, '/');
    },
    decode(token, secret){
        let [part1,part2,part3] = token.split('.');
        const newPart3  = this.sign([part1, part2].join('.'), secret);
        if(newPart3 === part3){ // 一样就说明没有篡改
            // part3 是被处理过  + = /的
            return JSON.parse(Buffer.from(this.base64urlUnescape(part2),'base64').toString('utf8'))
        }else{
            throw new Error('抱歉 令牌不对')
        }
    }
}


let server = http.createServer((req, res) => {
    if(req.url === '/login'){
        let token = jwt.encode({
            name:'ikki',
            id:100
        },secret)
        res.end(JSON.stringify({
            err:0,
            token,
            data:'登陆成功'
        }))
    }else if(req.url === '/validate'){
        let token = req.headers['authorization'] //jwt token    authorization：Bearer token
        if(token){
            let [, t] = token.split(' ');
            try{
                let payload = jwt.decode(t, secret); // 做签名比对
                res.end(JSON.stringify({
                    err: 0,
                    data: payload
                }));
            }catch(e){
                res.statusCode = 401;
                res.end(JSON.stringify({
                    err: 1,
                    data: '用户校验失败'
                }))
            }
        }
    }else{
        res.statusCode = 404
        res.end
    }
});


server.listen(3000);
